﻿module RestTestFunctions
open System
open RestfulObjects.Mvc
open System.Net.Http
open System.Net.Http.Headers
open System.IO
open Newtonsoft.Json.Linq
open RestfulObjects.Snapshot.Utility 
open RestfulObjects.Snapshot.Constants
open NUnit.Framework
open System.Collections.Generic
open System.Linq
open System.Web
open RestfulObjects.Mvc.Model

let mapCodeToType (code : string) : string = code
let mapTypeToCode (typ : string) : string = typ

let mapCodeToKey (code : string) : string = code
let mapKeyToCode (key : string) : string = key

let mutable ctt = mapCodeToType
let mutable ttc = mapTypeToCode

let mutable ctk = mapCodeToKey
let mutable ktc = mapKeyToCode

let testRoot = "http://localhost/"

let oneDay = new TimeSpan(1,0,0,0)

let oneHour = new TimeSpan(1,0,0)

let unprocessableEntity = box(422) :?> System.Net.HttpStatusCode

let preconditionHeaderMissing = box(428) :?> System.Net.HttpStatusCode

type partCmp (s : string) =
    let partS = s 
    override x.Equals (o : obj) =
        partS.StartsWith(o.ToString()) 
    override x.GetHashCode() = 
        partS.GetHashCode()
    override x.ToString() = 
        partS

type hrefType (href : string) =
    let h = href 
    member x.full with get() = sprintf "http://localhost/%s" h  
    override x.Equals (o : obj) =
        x.full  = o.ToString() 
    override x.GetHashCode() = 
        x.full.GetHashCode()
    override x.ToString() = 
        x.full
        
type typeType (mt, dt, et, simple) =
    let m = mt 
    let d = dt
    let e = et
    let s = simple
    member x.full 
        with get() =
            let mtString = sprintf "application/json; profile=\"urn:org.restfulobjects:repr-types/%s\"; charset=utf-8" m         
            let parmValue p = if s then sprintf "\"%s\"" p else sprintf "\"http://localhost/%s/%s\"" SegmentValues.DomainTypes  p
                    
            if d <> "" then       
                mtString + sprintf "; x-ro-domain-type=%s" (parmValue d)   
            else if e <> "" then             
                mtString + sprintf "; x-ro-element-type=%s" (parmValue e)
            else 
                mtString

    new (mt) = typeType(mt, "", "", false)
    new (mt, dt) = typeType(mt, dt, "", true)

    override x.Equals (o : obj) =
        x.full  = o.ToString() 
    override x.GetHashCode() = 
        x.full.GetHashCode()
    override x.ToString() = 
        x.full

type errorType (error : string) =
    let e = error 
    member x.getStart s =  e.Split([|" in "|], System.StringSplitOptions.None).[0]
    member x.toCompare with get() = x.getStart e
    override x.Equals (o : obj) =
        x.toCompare  = x.getStart (o.ToString())
    override x.GetHashCode() = 
        x.toCompare.GetHashCode()
    override x.ToString() = 
        x.toCompare

type TObject = 
    | TObjectJson of seq<TProp>
    | TObjectVal of obj 
    | TArray of seq<TObject> 
and TProp = TProperty of string * TObject

let makeProfile s = sprintf "\"urn:org.restfulobjects:repr-types/%s\"" s

let makeParm r n = sprintf ";%s=\"%s\"" r n 

let makeFriendly (s : string) = 
    let mutable newS = ""
    for c in s do  if Char.IsUpper(c) then  newS <- newS + " " + new string(c, 1)   else   newS <- newS + new string(c, 1)
    newS.Trim()

let wrap f (a, b, c, d) = f (a, c, d) 

let wrap1 f (a, b, c) = f (a, c) 

let jsonGetMsg (url : string) = 
    let message = new HttpRequestMessage(HttpMethod.Get, url)
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))
    message

let jsonGetMsgAndTag (url : string) tag = 
    let message = new HttpRequestMessage(HttpMethod.Get, url)
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))
    message.Headers.IfMatch.Add(new EntityTagHeaderValue(tag))
    message

let xmlGetMsg (url : string) = 
    let message = new HttpRequestMessage(HttpMethod.Get, url)
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"))
    message

let msgWithContent url content = 
    let message = new HttpRequestMessage()
    message.Content <- new StringContent(content)
    message.RequestUri <- new Uri(url)
    message.Content.Headers.ContentLength <- Nullable(int64(content.Length))
    message

let msgWithoutContent url  = 
    let message = new HttpRequestMessage()
    message.RequestUri <- new Uri(url)
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))
    //message.Content.Headers.ContentLength <- Nullable(int64(0))
    message

let msgWithoutContentWithTag url tag  = 
    let message = new HttpRequestMessage()
    message.RequestUri <- new Uri(url)
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))
    message.Headers.IfMatch.Add(new EntityTagHeaderValue(tag))
    //message.Content.Headers.ContentLength <- Nullable(int64(0))
    message

let jsonMsgWithContent url content = 
    let message = msgWithContent url content 
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))
   // message.Content.Headers.ContentType <- new MediaTypeWithQualityHeaderValue("application/json")
    message

let jsonMsgWithContentAndTag url content tag = 
    let message = msgWithContent url content 
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))
    message.Headers.IfMatch.Add(new EntityTagHeaderValue(tag))
   // message.Content.Headers.ContentType <- new MediaTypeWithQualityHeaderValue("application/json")
    message

let xmlMsgWithContent url content = 
    let message = msgWithContent url content 
    message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"))
    //message.Content.Headers.ContentType <- new MediaTypeWithQualityHeaderValue("application/xml")
    message

let jsonPostMsg url content = 
    let message = jsonMsgWithContent url content
    message.Method <- HttpMethod.Post
    message

let jsonPostMsgAndTag url content tag = 
    let message = jsonMsgWithContentAndTag url content tag
    message.Method <- HttpMethod.Post
    message

let jsonDeleteMsg url  = 
    let message = msgWithoutContent url
    message.Method <- HttpMethod.Delete
    message

let jsonDeleteMsgAndTag url tag = 
    let message = msgWithoutContentWithTag url tag
    message.Method <- HttpMethod.Delete
    message

let jsonPutMsg url content = 
    let message = jsonMsgWithContent url content
    message.Method <- HttpMethod.Put
    message

let jsonPutMsgAndTag url content tag = 
    let message = jsonMsgWithContentAndTag url content tag
    message.Method <- HttpMethod.Put
    message

let xmlPutMsg url content = 
    let message = xmlMsgWithContent url content
    message.Method <- HttpMethod.Put
    message

let xmlDeleteMsg url content = 
    let message = xmlMsgWithContent url content
    message.Method <- HttpMethod.Delete
    message

let xmlPostMsg url content = 
    let message = xmlMsgWithContent url content
    message.Method <- HttpMethod.Post
    message

//type selector() =
// 
//    interface Formatting.IFormatterSelector with
//        member x.SelectWriteFormatter (typ, formatterContext, formatters, mediaType) =
//            formatters |> Seq.head
//        member x.SelectReadFormatter (typ, formatterContext, formatters) = 
//            formatters |> Seq.head

let readSnapshotToJson (ss : HttpResponseMessage) = 
    // ReasAsStringAsync seems to hang so need to do this ......
    use s = ss.Content.ReadAsStreamAsync().Result
    s.Position <- 0L
    use sr = new StreamReader(s)
    sr.ReadToEnd()
  

let comp (a : obj) (b : obj) e = 
    Assert.AreEqual(a, b, e)   

let listProperties (result : JObject) = 
    (result |> Seq.map (fun i -> (i :?> JProperty).Name) |> Seq.fold (fun a s ->  a + " " + s) "Properties: " )

let listExpected (expected : seq<TProp>) = 
    (expected |> Seq.map (fun r -> match r with | TProperty(s, _) -> s) |> Seq.fold (fun a s ->  a + " " + s) "Expected: " )

let rec compareArray (expected : seq<TObject>) (result : JArray) =
    Assert.AreEqual (expected |> Seq.length, result.Count, "arrays")
    result |> Seq.zip expected 
           |> Seq.iter (fun i ->  compare (fst(i)) (snd(i)) )     

and compareObject (expected : seq<TProp>) (result : JObject) = 
    
    Assert.AreEqual (expected |> Seq.length, result.Count, ((listProperties result) + " " + (listExpected expected)) )

    let orderedResult = result |> Seq.sortBy (fun i -> (i :?> JProperty).Name)
    
    orderedResult  |> Seq.map (fun i -> (i :?> JProperty).Name)  
                   |> Seq.zip (expected |> Seq.sortBy (fun r -> match r with | TProperty(s, _) -> s) |> Seq.map (fun r -> match r with | TProperty(s, _) -> s))                                                    
                   |> Seq.iter (fun i -> comp (fst(i)) (snd(i)) ((listProperties result) + " " + (listExpected expected)) ) 

    orderedResult  |> Seq.map (fun i -> (i :?> JProperty).Value)  
                   |> Seq.zip (expected |> Seq.sortBy (fun r -> match r with | TProperty(s, _) -> s) |> Seq.map (fun r -> match r with | TProperty(_, o) -> o))                                                    
                   |> Seq.iter (fun i ->  compare (fst(i)) (snd(i)) ) 

and compare expected (result : JToken) = 
    match expected  with 
    | TObjectJson(sq) -> compareObject sq (result :?> JObject )
    | TObjectVal(o) ->  Assert.AreEqual(o, (result :?> JValue).Value) 
    | TArray(sq)  -> compareArray sq  (result :?> JArray )    


let getIndent i = 
    let oneIndent = "  "
    let rec makeIndent indent count = 
        if count = 0 then indent else makeIndent (indent + oneIndent) (count - 1)
    makeIndent "" i 

let rec toStringArray (expected : seq<TObject>) indent : string =
    
    (getIndent indent) + "[\n" + ( expected |> Seq.fold (fun i j -> i + (toString j indent)) "") + "\n],"

and toStringProp (expected : TProp) indent : string = 

    match expected with 
    | TProperty(i, j) ->   (getIndent indent) +  i  + ": "  + (toString j indent) + ",\n"

and toStringObject (expected : seq<TProp>) indent : string = 

    (getIndent indent) +  "{\n" +   ( if expected = null then "null" else  expected |> Seq.fold (fun i j -> i + (toStringProp j (indent + 1) )) "") + "\n},"
   
and toString expected indent : string  = 
    match expected  with 
    | TObjectJson(sq) -> toStringObject sq (indent + 1)
    | TObjectVal(o) ->  if o = null then "null" else  o.ToString() 
    | TArray(sq)  -> toStringArray sq  (indent + 1)


let makeLinkPropWithMethodAndTypesValue (meth : string) (rel : string) href typ dTyp eTyp simple vObj = 
     [ TProperty(JsonPropertyNames.Rel, TObjectVal(rel));
       TProperty(JsonPropertyNames.Href, TObjectVal(new hrefType(href)));
       TProperty(JsonPropertyNames.Type, TObjectVal(new typeType(typ, dTyp, eTyp, simple)));
       TProperty(JsonPropertyNames.Value, vObj);
       TProperty(JsonPropertyNames.Method, TObjectVal(meth)) ]


let makeLinkPropWithMethodAndTypes (meth : string) (rel : string) href typ dTyp eTyp simple = 
     [ TProperty(JsonPropertyNames.Rel, TObjectVal(rel));
       TProperty(JsonPropertyNames.Href, TObjectVal(new hrefType(href)));
       TProperty(JsonPropertyNames.Type, TObjectVal(new typeType(typ, dTyp, eTyp, simple)));
       TProperty(JsonPropertyNames.Method, TObjectVal(meth)) ]

let makeLinkPropWithMethod (meth : string) (rel : string) href typ dTyp = 
     [ TProperty(JsonPropertyNames.Rel, TObjectVal(rel));
       TProperty(JsonPropertyNames.Href, TObjectVal(new hrefType(href)));
       TProperty(JsonPropertyNames.Type, TObjectVal(new typeType(typ, dTyp)));
       TProperty(JsonPropertyNames.Method, TObjectVal(meth)) ]

let makeLinkPropWithMethodValue (meth : string) (rel : string) href typ dTyp vObj = 
     [ TProperty(JsonPropertyNames.Rel, TObjectVal(rel));
       TProperty(JsonPropertyNames.Href, TObjectVal(new hrefType(href)));
       TProperty(JsonPropertyNames.Type, TObjectVal(new typeType(typ, dTyp)));
       TProperty(JsonPropertyNames.Value, vObj);
       TProperty(JsonPropertyNames.Method, TObjectVal(meth)) ]


let makeHref href =  [ TProperty(JsonPropertyNames.Href, TObjectVal(new hrefType(href))) ]

let makeGetLinkProp = makeLinkPropWithMethod "GET"

let makePutLinkProp = makeLinkPropWithMethod "PUT"

let makePostLinkProp = makeLinkPropWithMethod "POST"

let makeDeleteLinkProp = makeLinkPropWithMethod "DELETE"
  
let makeIconLink() = 
        [ TProperty(JsonPropertyNames.Rel, TObjectVal(RelValues.Icon) );
          TProperty(JsonPropertyNames.Href, TObjectVal(new hrefType("images/Default.gif")) );
          TProperty(JsonPropertyNames.Type, TObjectVal("image/gif") );
          TProperty(JsonPropertyNames.Method, TObjectVal("GET") ) ]

let makeActionMemberFormal oType  mName (oName : string) rType =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index) 
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName     
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]

let makeActionMemberVoidFormal oType  mName (oName : string) =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)  
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]


let makeActionMember oType  mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1 
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                               TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                               TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                               TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                               TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]

let makeActionMemberSimple oType  mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1 
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "") ]))]


let makeActionMemberString oType mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1   
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal("string"));
                                                                  TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                                  TProperty(JsonPropertyNames.MaxLength, TObjectVal(0));
                                                                  TProperty(JsonPropertyNames.Pattern, TObjectVal(""));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]

let makeActionMemberNumber oType mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1   
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal("number"));
                                                                  TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]


let makeActionMemberStringSimple oType mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1   
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal("string"));
                                                                  TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                                  TProperty(JsonPropertyNames.MaxLength, TObjectVal(0));
                                                                  TProperty(JsonPropertyNames.Pattern, TObjectVal(""));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "") ]))]

let makeActionMemberNumberSimple oType mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1   
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal("number"));
                                                                  TProperty(JsonPropertyNames.Format, TObjectVal(rType));                                                               
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "") ]))]



let makeActionMemberWithType oType mName (oName : string) fName desc rType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index) 
        let order = if desc = "" then 0 else 1  
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]

let makeVoidActionMember oType mName (oName : string) fName desc hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index) 
        let order = if desc = "" then 0 else 1  
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));                                             
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");                                     
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]

let makeVoidActionMemberSimple oType mName (oName : string) fName desc hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 1   
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));  
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));                                           
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "") ]))]



let makeActionMemberCollection oType  mName (oName : string)  fName desc rType eType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 2    
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName      
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                                  TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                                  TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                                  TProperty(JsonPropertyNames.ElementType, TObjectVal(eType));
                                                                  TProperty(JsonPropertyNames.PluralName, TObjectVal("Most Simples"));
                                                                  TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                                  TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.ElementType (sprintf "domain-types/%s" eType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]

let makeActionMemberCollectionSimple oType  mName (oName : string)  fName desc rType eType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let order = if desc = "" then 0 else 2       
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                               TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                               TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                               TProperty(JsonPropertyNames.ElementType, TObjectVal(eType));
                                                               TProperty(JsonPropertyNames.PluralName, TObjectVal("Most Simples"));
                                                               TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                               TProperty(JsonPropertyNames.HasParams, TObjectVal(hParms))]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "") ]))]


let makeActionMemberCollectionFormal oType  mName (oName : string)  fName desc rType eType hParms =
        let index = oName.IndexOf("/")
        let oTypeName =  if index = -1 then oName else  oName.Substring(0, index)
        let detailsRelValue = RelValues.Details + makeParm RelParamValues.Action mName    
        [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Action) );
          TProperty(JsonPropertyNames.Id, TObjectVal(mName));
          TProperty(JsonPropertyNames.Extensions, TObjectJson([]));
          TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/actions/%s" oType oName mName) RepresentationTypes.ObjectAction "");
                                                      TObjectJson( makeGetLinkProp RelValues.ReturnType (sprintf "domain-types/%s" rType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.ElementType (sprintf "domain-types/%s" eType ) RepresentationTypes.DomainType "");
                                                      TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/actions/%s" oTypeName mName) RepresentationTypes.ActionDescription "") ]))]



let makePropertyMemberShort oType mName (oName : string) fName desc rType opt (oValue : TObject) (dValue : TProp list) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2    
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName 

      let detailsLink = 
            if dValue |> Seq.isEmpty then 
                makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty ""
            else 
                makeLinkPropWithMethodValue "GET" detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "" (TObjectJson(dValue))

      
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( detailsLink);
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]

let makePropertyMemberShortNoDetails oType mName (oTypeName : string) fName desc rType opt (oValue : TObject) =
      let order = if desc = "" then 0 else 2 
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "")  ]))]



let makePropertyMemberFull oType mName  (oName : string) fName desc opt (oValue : TObject) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2 
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName 
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("number"));  
                                                             TProperty(JsonPropertyNames.Format, TObjectVal("integer"));  
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));                                       
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]

let makePropertyMemberFullNoDetails oType mName (oTypeName : string) fName desc opt (oValue : TObject) =
      let order = if desc = "" then 0 else 2 
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("number"));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal("integer"));  
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));                                           
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]



let makePropertyMemberDateTime oType mName (oName : string) fName desc opt (oValue : TObject) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 4
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("string"));
                                                             TProperty(JsonPropertyNames.MaxLength, TObjectVal(0));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal("date-time"));
                                                             TProperty(JsonPropertyNames.Pattern, TObjectVal(""));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]


let makePropertyMemberString oType mName (oName : string) fName desc opt (oValue : TObject) (dValue : TProp list) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName

      let detailsLink = 
            if dValue |> Seq.isEmpty then 
                makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty ""
            else 
                makeLinkPropWithMethodValue "GET" detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "" (TObjectJson(dValue))

      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("string"));
                                                             TProperty(JsonPropertyNames.MaxLength, TObjectVal(101));
                                                             TProperty(JsonPropertyNames.Pattern, TObjectVal("[A-Z]"));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal("string"));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( detailsLink);
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]

let makePropertyMemberWithType oType mName (oName : string) fName desc rType opt (oValue : TObject) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "")  ]))]

let makePropertyMemberWithNumber oType mName (oName : string) fName desc rType opt (oValue : TObject) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("number"));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "")  ]))]


let makePropertyMemberWithFormat oType mName (oName : string) fName desc rType opt (oValue : TObject) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("string"));
                                                             TProperty(JsonPropertyNames.MaxLength, TObjectVal(0));
                                                             TProperty(JsonPropertyNames.Pattern, TObjectVal(""));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]



let makePropertyMemberWithTypeNoValue oType mName (oName : string) fName desc rType opt =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("string"));
                                                             TProperty(JsonPropertyNames.MaxLength, TObjectVal(0));
                                                             TProperty(JsonPropertyNames.Pattern, TObjectVal(""));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "") ]))]

let makePropertyMemberFormal oType mName (oName : string) (oValue : TObject) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "");
                                                    TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/properties/%s" oTypeName mName) RepresentationTypes.PropertyDescription "")  ]))]

let makePropertyMemberSimple oType mName (oName : string) fName desc rType opt (oValue : TObject) =
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "")  ]))]

let makePropertyMemberSimpleNumber oType mName (oName : string) fName desc rType opt (oValue : TObject) =
      let order = if desc = "" then 0 else 3
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal("number"));
                                                             TProperty(JsonPropertyNames.Format, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.Optional, TObjectVal(opt))]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "")  ]))]



let makePropertyMemberNone oType mName (oName : string)  (oValue : TObject) =
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Property mName  
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Property) );
        TProperty(JsonPropertyNames.Id, TObjectVal(mName));
        TProperty(JsonPropertyNames.Value, oValue);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([]));
        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( makeGetLinkProp detailsRelValue (sprintf "%s/%s/properties/%s" oType oName mName) RepresentationTypes.ObjectProperty "")  ]))]


let makePropertyMember oType mName oName fName (oValue : TObject) = makePropertyMemberFull "objects" mName oName fName "" false oValue 

let makeCollectionMemberType mName (oName : string) fName desc rType size cType cName =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Collection mName
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.PluralName, TObjectVal(cName));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.ElementType, TObjectVal(cType))]));
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson( makeLinkPropWithMethodAndTypes "GET" detailsRelValue (sprintf "objects/%s/collections/%s" oName mName) RepresentationTypes.ObjectCollection "" cType true);
                                                     TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/collections/%s" oTypeName mName) RepresentationTypes.CollectionDescription "") ]))]

let makeCollectionMemberTypeValue mName (oName : string) fName desc rType size cType cName cValue (dValue : TProp list) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Collection mName

      let detailsLink = makeLinkPropWithMethodAndTypesValue "GET" detailsRelValue (sprintf "objects/%s/collections/%s" oName mName) RepresentationTypes.ObjectCollection "" cType true (TObjectJson(dValue))

      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Value, cValue );
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.PluralName, TObjectVal(cName));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.ElementType, TObjectVal(cType))]));
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson( detailsLink);
                                                     TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/collections/%s" oTypeName mName) RepresentationTypes.CollectionDescription "") ]))]



let makeCollectionMember mName (oName : string) fName desc rType size = makeCollectionMemberType mName (oName : string) fName desc rType size (ttc "RestfulObjects.Test.Data.MostSimple") "Most Simples"

let makeCollectionMemberSimpleTypeValue mName (oName : string) fName desc rType size cType cName cValue (dValue : TProp list) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Collection mName
     
      let detailsLink = makeLinkPropWithMethodAndTypesValue "GET" detailsRelValue (sprintf "objects/%s/collections/%s" oName mName) RepresentationTypes.ObjectCollection "" cType true (TObjectJson(dValue))

      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Value, cValue );
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.PluralName, TObjectVal(cName));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.ElementType, TObjectVal(cType))]));
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson(detailsLink) ]))]

   
let makeCollectionMemberSimpleType mName (oName : string) fName desc rType size cType cName =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Collection mName
     
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.PluralName, TObjectVal(cName));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.ElementType, TObjectVal(cType))]));
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson( makeLinkPropWithMethodAndTypes "GET" detailsRelValue (sprintf "objects/%s/collections/%s" oName mName) RepresentationTypes.ObjectCollection "" cType true) ]))]

let makeCollectionMemberSimple mName (oName : string) fName desc rType size = makeCollectionMemberSimpleType mName oName fName desc rType size (ttc "RestfulObjects.Test.Data.MostSimple") "Most Simples"

let makeCollectionMemberFormalTypeValue mName  (oName : string) size cType cValue (dValue : TProp list) =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Collection mName
      
      let detailsLink = makeLinkPropWithMethodAndTypesValue "GET" detailsRelValue (sprintf "objects/%s/collections/%s" oName mName) RepresentationTypes.ObjectCollection "" cType false (TObjectJson(dValue))

      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Value, cValue );
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson( detailsLink);
                                                     TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/collections/%s" oTypeName mName) RepresentationTypes.CollectionDescription "") ]));
        TProperty(JsonPropertyNames.Extensions, TObjectJson([ ]))]


let makeCollectionMemberFormalType mName  (oName : string) size cType =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let detailsRelValue = RelValues.Details + makeParm RelParamValues.Collection mName
      
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson( makeLinkPropWithMethodAndTypes "GET" detailsRelValue (sprintf "objects/%s/collections/%s" oName mName) RepresentationTypes.ObjectCollection "" cType false);
                                                     TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/collections/%s" oTypeName mName) RepresentationTypes.CollectionDescription "") ]));
        TProperty(JsonPropertyNames.Extensions, TObjectJson([ ]))]

let makeCollectionMemberFormal mName  (oName : string) size = makeCollectionMemberFormalType mName  oName size (ttc "RestfulObjects.Test.Data.MostSimple") 

let makeCollectionMemberNoDetails mName oName fName desc =
      let order = if desc = "" then 0 else 2
      let mst = ttc "RestfulObjects.Test.Data.MostSimple"
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(ResultTypes.List));
                                                             TProperty(JsonPropertyNames.PluralName, TObjectVal("Most Simples"));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.ElementType, TObjectVal(mst))]));
        TProperty(JsonPropertyNames.Links, TArray ([  ]))]

let makeCollectionMemberWithValue mName (oName : string) fName desc rType values size cType cText =
      let oTypeName = oName.Substring(0, oName.IndexOf("/"))
      let order = if desc = "" then 0 else 2
      //let mst = ttc "RestfulObjects.Test.Data.MostSimple"
      [ TProperty(JsonPropertyNames.MemberType, TObjectVal(MemberTypes.Collection) );
        TProperty(JsonPropertyNames.Id, TObjectVal( mName) );
        TProperty(JsonPropertyNames.Size, TObjectVal( size) );
        TProperty(JsonPropertyNames.Value, values);
        TProperty(JsonPropertyNames.Extensions, TObjectJson([TProperty(JsonPropertyNames.FriendlyName, TObjectVal(fName));
                                                             TProperty(JsonPropertyNames.Description, TObjectVal(desc));
                                                             TProperty(JsonPropertyNames.ReturnType, TObjectVal(rType));
                                                             TProperty(JsonPropertyNames.PluralName, TObjectVal(cText));
                                                             TProperty(JsonPropertyNames.MemberOrder, TObjectVal(order));
                                                             TProperty(JsonPropertyNames.ElementType, TObjectVal(cType))]));
        TProperty(JsonPropertyNames.Links, TArray ([ TObjectJson( makeGetLinkProp RelValues.DescribedBy (sprintf "domain-types/%s/collections/%s" oTypeName mName) RepresentationTypes.CollectionDescription "") ]))]


let makeServiceActionMember mName oName rType = makeActionMember "services" mName oName (makeFriendly(mName)) "" rType true

let makeServiceActionMemberSimple mName oName rType = makeActionMemberSimple "services" mName oName (makeFriendly(mName)) "" rType true

let makeObjectActionMember mName oName rType  = makeActionMember "objects" mName oName (makeFriendly(mName)) "" rType true

let makeObjectActionMemberSimple mName oName rType  = makeActionMemberSimple "objects" mName oName (makeFriendly(mName)) "" rType true

let makeObjectActionCollectionMember mName oName eType  = makeActionMemberCollection "objects" mName oName (makeFriendly(mName)) "" ResultTypes.List eType true

let makeObjectActionCollectionMemberSimple mName oName eType  = makeActionMemberCollectionSimple "objects" mName oName (makeFriendly(mName)) "" ResultTypes.List eType true

let makeObjectActionCollectionMemberNoParms mName oName eType  = makeActionMemberCollection "objects" mName oName (makeFriendly(mName)) "" ResultTypes.List eType false

let makeObjectActionCollectionMemberNoParmsSimple mName oName eType  = makeActionMemberCollectionSimple "objects" mName oName (makeFriendly(mName)) "" ResultTypes.List eType false

let makeObjectActionCollectionMemberFormal mName oName eType  = makeActionMemberCollectionFormal "objects" mName oName (makeFriendly(mName)) "" ResultTypes.List eType false

let makeObjectActionVoidMember mName oName  = makeVoidActionMember "objects" mName oName (makeFriendly(mName)) ""  false

let makeObjectActionVoidMemberSimple mName oName  = makeVoidActionMemberSimple "objects" mName oName (makeFriendly(mName)) ""  false

let makeServiceActionMemberNoParms mName oName rType  = makeActionMember "services" mName oName (makeFriendly(mName)) "" rType false

let makeServiceActionMemberNoParmsSimple mName oName rType  = makeActionMemberSimple "services" mName oName (makeFriendly(mName)) "" rType false

let makeObjectActionMemberNoParms mName oName rType  = makeActionMember "objects" mName oName (makeFriendly(mName)) "" rType false

let makeObjectActionMemberNoParmsSimple mName oName rType  = makeActionMemberSimple "objects" mName oName (makeFriendly(mName)) "" rType false

let makeObjectPropertyMember mName oName fName (oValue : TObject) =  makePropertyMember "objects" mName oName fName oValue 

let makeObjectPropertyMemberWithDesc mName oName fName desc opt (oValue : TObject) =  makePropertyMemberFull "objects" mName oName fName desc opt oValue 

let makeServiceActionCollectionMember mName oName eType  = makeActionMemberCollection "services" mName oName (makeFriendly(mName)) "" ResultTypes.List eType true

let makeServiceActionCollectionMemberNoParms mName oName eType  = makeActionMemberCollection "services" mName oName (makeFriendly(mName)) "" ResultTypes.List eType false

let makeServiceActionVoidMember mName oName  = makeVoidActionMember "services" mName oName (makeFriendly(mName)) ""  false

let assertTransactionalCache  (message : HttpResponseMessage) = 
    Assert.AreEqual(true, message.Headers.CacheControl.NoCache)
    Assert.AreEqual("no-cache", message.Headers.Pragma.ToString())
    Assert.AreEqual(message.Headers.Date, message.Content.Headers.Expires)

let assertConfigCache secs  (message : HttpResponseMessage) = 
    let ts = new TimeSpan(0, 0, secs)
    Assert.AreEqual(ts, message.Headers.CacheControl.MaxAge)
    Assert.IsTrue(message.Headers.Date.HasValue)
    let expire = message.Headers.Date.Value + ts
    Assert.AreEqual(expire, message.Content.Headers.Expires)

let assertUserInfoCache (message : HttpResponseMessage) = 
    Assert.AreEqual(oneHour, message.Headers.CacheControl.MaxAge)
    Assert.IsTrue(message.Headers.Date.HasValue)
    let expire = message.Headers.Date.Value + oneHour
    Assert.AreEqual(expire, message.Content.Headers.Expires)

let assertNonExpiringCache (message : HttpResponseMessage) = 
    Assert.AreEqual(oneDay, message.Headers.CacheControl.MaxAge)
    Assert.IsTrue(message.Headers.Date.HasValue)
    let expire = message.Headers.Date.Value + oneDay
    Assert.AreEqual(expire, message.Content.Headers.Expires)

let CreateSingleValueArg (m : JObject) = ModelBinderUtils.CreateSingleValueArgument(m)
     
let CreateArgMap (m : JObject) = ModelBinderUtils.CreateArgumentMap(m)

let CreateReservedArgs (s : string) = ModelBinderUtils.CreateReservedArguments(s)
   
let CreateArgMapFromUrl (s : string) = ModelBinderUtils.CreateSimpleArgumentMap(s)

let CreatePersistArgMap (m : JObject) = ModelBinderUtils.CreatePersistArgMap(m)

let GetDomainType (m : JObject) = 
  
    let dm = m.["x-ro-domain-model"]
    let dt = m.["domainType"]
    let lks = m.["links"]
   
    let dmm = if dm = null then null else (dm :?> JValue).Value   :?> string
 
    if (dt <> null && dmm <> "formal") then 
        if dt = null then "" else (dt :?> JValue).Value   :?> string
    else if (lks <> null && dmm <> "simple" ) then 
        let rel = ((lks.First.["rel"] :?> JValue).Value :?> string)
        if (rel <> "describedby") then raise ( new Exception())
        let href = lks.First.["href"]
        let dtRef = (href :?> JValue).Value :?> string
        if dtRef.StartsWith("http://localhost/domain-types/") then 
            let ss = dtRef.Substring("http://localhost/domain-types/".Length )
            ss
        else 
            ""
    else 
        ""
               

   